﻿/*
 * Created by SharpDevelop.
 * User: alexandre
 * Date: 02/07/2013
 * Time: 21:52
 *
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using SVM_Sharp.Controller;
using SVM_Sharp.Model;

namespace SVM_Sharp
{
    public class ParameterError : System.Exception
    {
        public string m_str = "";
    }

    /// <summary>
    /// Description of SVM_SharpCtrl.
    /// </summary>
    public class SVM_SharpCtrl
    {
        private SVM_SharpData m_data = null;

        public static int ID_TREINO = 0;
        public static int ID_TESTE = 1;

        public static int ID_ACCURACY = 0;
        public static int ID_KERNEL = 1;
        public static int ID_SCALED = 2;
        public static int ID_GAMMA = 3;
        public static int ID_COEFFICIENT0 = 4;
        public static int ID_DEGREE = 5;
        public static int ID_C = 6;
        public static int ID_WEIGHTPOS = 7;
        public static int ID_WEIGHTNEG = 8;
        public static int ID_RESULTADOS = 9;
        public static int ID_TREINO_FILE = 10;
        public static int ID_TESTE_FILE = 11;
        public static int ID_POS_PERCENT = 12;
        public static int ID_NEG_PERCENT = 13;
        public static int ID_OFF_LABELS = 14;
        public static int ID_TRAIN_TIME = 15;
        public static int ID_PREDI_TIME = 16;
        public static int ID_MULTITHREAD = 17;

        public SVM_SharpCtrl()
        {
            m_data = new SVM_SharpData();
        }

        public void armazenarSVMDataAtual()
        {
            m_data = new SVM_SharpData();
        }

        public void executarTreino()
        {
            m_data.model = SVM.Training.Train(m_data.treino, m_data.parameters);
        }

        public void escreverModel()
        {
            SVM.Model.Write("model.txt", m_data.model);
        }

        public void lerArquivo(string _filePath, int _tipo)
        {
            if (_tipo.Equals(ID_TESTE))
                m_data.teste = SVM.Problem.Read(_filePath, m_data.listaDesabilitadas);
            else if (_tipo.Equals(ID_TREINO))
                m_data.treino = SVM.Problem.Read(_filePath, m_data.listaDesabilitadas);
            else
                System.Diagnostics.Debug.Assert(false);
        }

        public void atribuirListaColunasDesabilitadas(int[] _listaDesabilitadas)
        {
            m_data.listaDesabilitadas = _listaDesabilitadas;
        }

        public void preencherParametros(Parametros _parametros)
        {
            SVM.Parameter newParam = new SVM.Parameter();
            newParam.Scale = _parametros.getScale();
            newParam.C = _parametros.getC();
            newParam.Weights[1] = _parametros.getPesoPositivo();
            newParam.Weights[-1] = _parametros.getPesoNegativo();
            newParam.KernelType = getKernelType(_parametros.getKernel());
            newParam.Gamma = _parametros.getGamma();
            newParam.Coefficient0 = _parametros.getCoef();
            newParam.Degree = _parametros.getDegree();
            SVM.PARALLEL_MODE.ENABLE_MULTI_THREAD = _parametros.getMultithread();

            m_data.parameters = newParam;
        }

        public void preencherParametros(FormEditParameters formParameters)
        {
            SVM.Parameter newParam = new SVM.Parameter();

            newParam.Scale = formParameters.IsScaleCheckd();

            if (formParameters.txt_c.Text.Length != 0)
            {
                try
                {
                    double value;
                    if (!double.TryParse(formParameters.txt_c.Text, out value))
                    {
                        formParameters.txt_c.Text = formParameters.txt_c.Text.Replace('.', ',');
                    }
                    newParam.C = System.Convert.ToDouble(formParameters.txt_c.Text);
                }
                catch (System.Exception x)
                {
                    ParameterError pe = new ParameterError();
                    pe.m_str = "Erro no parametro C:\n " + x;
                    throw pe;
                }
            }
            else
            {
                formParameters.txt_c.Text = newParam.C.ToString();
            }

            if (formParameters.txt_weightP.Text.Length != 0)
            {
                try
                {
                    newParam.Weights[1] = System.Convert.ToDouble(formParameters.txt_weightP.Text);
                }
                catch (System.Exception x)
                {
                    ParameterError pe = new ParameterError();
                    pe.m_str = "Erro no parametro Weight +1:\n " + x;
                    throw pe;
                }
            }
            else
            {
                formParameters.txt_weightP.Text = newParam.Weights[1].ToString();
            }

            if (formParameters.txt_weightN.Text.Length != 0)
            {
                try
                {
                    newParam.Weights[-1] = System.Convert.ToDouble(formParameters.txt_weightN.Text);
                }
                catch (System.Exception x)
                {
                    ParameterError pe = new ParameterError();
                    pe.m_str = "Erro no parametro Weight -1:\n " + x;
                    throw pe;
                }
            }
            else
            {
                formParameters.txt_weightN.Text = newParam.Weights[-1].ToString();
            }

            if (formParameters.rbx_lin.Checked == true)
                newParam.KernelType = SVM.KernelType.LINEAR;

            if (formParameters.rbx_RBF.Checked == true || formParameters.rbx_sig.Checked == true || formParameters.rbx_pol.Checked == true)
            {
                newParam.KernelType = SVM.KernelType.RBF;
                if (formParameters.txt_gamma.Text.Length > 0)
                {
                    try
                    {
                        newParam.Gamma = System.Convert.ToDouble(formParameters.txt_gamma.Text);
                    }
                    catch (System.Exception x)
                    {
                        ParameterError pe = new ParameterError();
                        pe.m_str = "Erro no parametro Gamma:\n " + x;
                        throw pe;
                    }
                }
                else
                {
                    formParameters.txt_gamma.Text = newParam.Gamma.ToString();
                }
            }

            if (formParameters.rbx_sig.Checked == true || formParameters.rbx_pol.Checked == true)
            {
                newParam.KernelType = SVM.KernelType.SIGMOID;
                if (formParameters.txt_coef.Text.Length > 0)
                {
                    try
                    {
                        newParam.Coefficient0 = System.Convert.ToDouble(formParameters.txt_coef.Text);
                    }
                    catch (System.Exception x)
                    {
                        ParameterError pe = new ParameterError();
                        pe.m_str = "Erro no parametro Coefficient0:\n " + x;
                        throw pe;
                    }
                }
                else
                {
                    formParameters.txt_coef.Text = newParam.Coefficient0.ToString();
                }
            }

            if (formParameters.rbx_pol.Checked == true)
            {
                newParam.KernelType = SVM.KernelType.POLY;
                if (formParameters.txt_degree.Text.Length > 0)
                {
                    try
                    {
                        newParam.Degree = System.Convert.ToInt32(formParameters.txt_degree.Text);
                    }
                    catch (System.Exception x)
                    {
                        ParameterError pe = new ParameterError();
                        pe.m_str = "Erro no parametro Degree:\n " + x;
                        throw pe;
                    }
                }
                else
                {
                    formParameters.txt_degree.Text = newParam.Degree.ToString();
                }
            }

            m_data.parameters = newParam;
        }

        internal void resetarScale()
        {
            m_data.range = null;
        }

        internal void executarComputeRange(int _tipo)
        {
            if (_tipo.Equals(ID_TREINO))
                m_data.range = SVM.RangeTransform.Compute(m_data.treino);
            else if (_tipo.Equals(ID_TESTE))
                m_data.range = SVM.RangeTransform.Compute(m_data.teste);
            else
                System.Diagnostics.Debug.Assert(false);
        }

        internal void executarScale(int _tipo)
        {
            SVM.Problem prob = null;
            if (_tipo.Equals(SVM_SharpCtrl.ID_TESTE))
            {
                prob = m_data.teste;
            }
            else if (_tipo.Equals(SVM_SharpCtrl.ID_TREINO))
            {
                prob = m_data.treino;
            }

            SVM.Problem scaled = SVM.Scaling.Scale(m_data.range, prob);
            prob.Count = scaled.Count;
            prob.MaxIndex = scaled.MaxIndex;
            prob.X = scaled.X;
            prob.Y = scaled.Y;

            if (_tipo.Equals(SVM_SharpCtrl.ID_TESTE))
            {
                m_data.teste = prob;
            }
            else if (_tipo.Equals(SVM_SharpCtrl.ID_TREINO))
            {
                m_data.treino = prob;
            }
        }

        internal bool estaTreinoScaled()
        {
            return m_data.range != null;
        }

        internal void escreverSaida(int _tipo, String _filePath)
        {
            if (_tipo.Equals(ID_TESTE))
            {
                SVM.Problem.Write(_filePath, m_data.teste);
            }
            else if (_tipo.Equals(ID_TREINO))
            {
                SVM.Problem.Write(_filePath, m_data.treino);
            }
        }

        internal void resetarResultados()
        {
            m_data.resultados = new double[5];
        }

        internal void executarPredict(String _outFilePath)
        {
            m_data.resultados = SVM.Prediction.Predict_Matriz(m_data.teste, _outFilePath, m_data.model, false);
        }

        internal void preencherMatrizConfusao(FormConfusionMatrix formConfusionMatrix)
        {
            formConfusionMatrix.Gera_matriz_conf(m_data.resultados);
        }

        internal int obterMaxIndex(int _tipo)
        {
            if (_tipo.Equals(ID_TREINO))
                return m_data.treino.MaxIndex;
            else if (_tipo.Equals(ID_TESTE))
                return m_data.teste.MaxIndex;
            else
                System.Diagnostics.Debug.Assert(false);

            return -1;
        }

        internal void preencherResultados(ref System.Data.DataRow tmprow)
        {
            tmprow[ID_ACCURACY] = System.String.Format("{0:0.##}", m_data.resultados[0] * 100) + " %";
            tmprow[ID_KERNEL] = m_data.parameters.KernelType;
            tmprow[ID_GAMMA] = m_data.parameters.Gamma;
            tmprow[ID_COEFFICIENT0] = m_data.parameters.Coefficient0;
            tmprow[ID_DEGREE] = m_data.parameters.Degree;
            tmprow[ID_C] = m_data.parameters.C;
            tmprow[ID_WEIGHTPOS] = m_data.parameters.Weights[1];
            tmprow[ID_WEIGHTNEG] = m_data.parameters.Weights[-1];
            tmprow[ID_RESULTADOS] = m_data.resultados;
            tmprow[ID_MULTITHREAD] = SVM.PARALLEL_MODE.ENABLE_MULTI_THREAD;

            if ((m_data.resultados[1] + m_data.resultados[2]) == 0)
                tmprow[ID_POS_PERCENT] = System.String.Format("{0:0.##}", 0) + " %";
            else
                tmprow[ID_POS_PERCENT] = System.String.Format("{0:0.##}", (m_data.resultados[1] / (m_data.resultados[1] + m_data.resultados[2])) * 100) + " %";

            if ((m_data.resultados[3] + m_data.resultados[4]) == 0)
                tmprow[ID_NEG_PERCENT] = System.String.Format("{0:0.##}", 0) + " %";
            else
            {
                string ss = System.String.Format("{0:0.##}", (m_data.resultados[3] / (m_data.resultados[3] + m_data.resultados[4])) * 100) + " %";
                tmprow[ID_NEG_PERCENT] = ss;
            }
        }

        internal void atribuirResultados(double[] _results)
        {
            m_data.resultados = _results;
        }

        internal void parameterSelection()
        {
            if (m_data.treino == null)
                return;

            double C, gamma;
            if (m_data.parameters == null)
                m_data.parameters = new SVM.Parameter();

            SVM.ParameterSelection.Grid(m_data.treino, m_data.parameters, "out_parameterSel.txt", out C, out gamma);

            m_data.parameters.C = C;
            m_data.parameters.Gamma = gamma;
        }

        private SVM.KernelType getKernelType(int kernel)
        {
            switch (kernel)
            {
                case Defines.TIPO_KERNEL_LINEAR:
                    return SVM.KernelType.LINEAR;

                case Defines.TIPO_KERNEL_RBF:
                    return SVM.KernelType.RBF;

                case Defines.TIPO_KERNEL_SIGMOIDE:
                    return SVM.KernelType.SIGMOID;

                case Defines.TIPO_KERNEL_POLINOMIAL:
                    return SVM.KernelType.POLY;
            }
            return SVM.KernelType.LINEAR;
        }
    }
}